package org.reliablesource.prism.gef.editor.model;

import java.io.Serializable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.Platform;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.draw2d.geometry.Rectangle;
import org.reliablesource.prism.core.IPrismAnnotation;
import org.reliablesource.prism.core.IPrismScreen;

/**
 * A container for a Screen. This is the "root" of the model data structure.
 * 
 * @author Dennis Park
 */
public class ScreenAdapter implements IAdaptable, Serializable {

	private static final long serialVersionUID = -1928650817757753655L;

	/** Property ID to use when a child is added to this diagram. */
	public static final String CHILD_ADDED_PROP = "PrismScreen.ChildAdded";

	/** Property ID to use when a child is removed from this diagram. */
	public static final String CHILD_REMOVED_PROP = "PrismScreen.ChildRemoved";

	public static final String SCREEN_CHILDREN = "PrismScreen.Children";
	
	public static final String SCREEN_START_PT = "PrismScreen.StartPt";
	public static final String SCREEN_END_PT = "PrismScreen.EndPt";

	private List 	childrenGraphicObjects = new LinkedList();

	private IPrismScreen screen;

	public ScreenAdapter(final IPrismScreen _prismUnit) {
		super();
		screen = _prismUnit;
	}

	/**
	 * Add a PointerLocation to this diagram.
	 * 
	 * @param _child
	 *            a non-null instance
	 * @return true, if the was added, false otherwise
	 */
	public boolean addChild(final Object _child) {

		if (_child != null && !childrenGraphicObjects.contains(_child)) {
			childrenGraphicObjects.add(_child);
			if (_child instanceof PointerLocation) {
				PointerLocation ptrLoc = (PointerLocation) _child;
				if(screen.getPointerStart() == null  || screen.getPointerStart().x == -1)
					screen.setPointerStart(ptrLoc.getJLocation());

			} else if (_child instanceof StickyNoteAdapter) {
				StickyNoteAdapter note = (StickyNoteAdapter) _child;
				screen.addAnnotation(note.getAnnotation());
			}			
			if(!(_child instanceof WireBendpoint))
				screen.firePropertyChange(CHILD_ADDED_PROP, null, _child);
			

			screenDumpChildren();
			return true;
		}
		return false;
	}

	/**
	 * Return a List of Model Children in this diagram. The returned List should
	 * not be modified.
	 * 
	 */
	public List getModelChildren() {
		return childrenGraphicObjects;
	}

	/**
	 * Remove a InfoLabel from this diagram.
	 * 
	 * @param _child
	 *            a non-null InfoLabel instance;
	 * @return true, if the InfoLabel was removed, false otherwise
	 */
	public boolean removeChild(final Object _child) {

		if (_child != null && childrenGraphicObjects.contains(_child)) {
			childrenGraphicObjects.remove(_child);
			if (_child instanceof PointerLocation) {
				PointerLocation ptrLoc = (PointerLocation) _child;
				if(ptrLoc.getJLocation().equals(screen.getPointerStart()))
					screen.setPointerStart(new java.awt.Point(-1, -1));
			} else if (_child instanceof StickyNoteAdapter) {
				StickyNoteAdapter note = (StickyNoteAdapter) _child;
				screen.removeAnnotation(note.getAnnotation());
			}
			if(!(_child instanceof WireBendpoint))
				screen.firePropertyChange(CHILD_REMOVED_PROP, null, _child);
			

			screenDumpChildren();
			return true;
		}
		return false;
	}
	
	/**
	 * 
	 * @param _index
	 * @param _wbp
	 * @return
	 */
	public boolean insertBendpoint(int _index, WireBendpoint _wbp){
		WireBendpoint bendPt =  _wbp;
		return screen.addPathLocation(_index, bendPt.getJLocation());
	}
	
	/**
	 * 			//	Since the WireBendpoint has not EditPart we do not need to 
			//		trigger this event.
	 * @param _index
	 * @param _wbp
	 * @return
	 */
	public boolean removeBendpoint(int _index, WireBendpoint _wbp){
			WireBendpoint bendPt =  _wbp;
			screen.removePathLocation(_index,bendPt.getJLocation());
			return true;
	}
	

	/**
	 * Return the property value for the given propertyId, or null.
	 */
	public Object getPropertyValue(final Object _propertyId) {
		if (IPrismScreen.IMAGE_PATH.equals(_propertyId))
			return screen.getImageFilePath() + screen.getName() + "."
					+ screen.getImageFileType();
		else if (ScreenAdapter.SCREEN_CHILDREN.equals(_propertyId))
			return getModelChildren();
		else
			return null;
	}

	/**
	 * Set the property value for the given property id.
	 */
	public void setPropertyValue(final Object _propertyId, final Object _value) {
		screenDumpChildren();
		//
		// if (IPrismScreen.IMAGE_PATH.equals(propertyId)) {
		// Object old = screen.getImageFilePath() + screen.getName() + "." +
		// screen.getImageFileType();
		// String newPath = (String) value;
		// // String [] splitType = newPath.split(".");
		// // String type = splitType[splitType.length].trim();
		// // screen.setImageFileType(type);
		// // System.err.println("Type: " + type);
		//			
		// String [] splitSep = newPath.split("\\");
		// String name = splitSep[splitSep.length-1].trim();
		// // name = name.replaceFirst(type, "");
		// screen.setName(name.trim());
		// System.err.println("Name:" + name);
		//			
		// // String location = splitSep[0].replaceFirst(name.trim(), "");
		// String location = newPath.replaceFirst(name, "");
		// screen.setImageFilePath(location.trim());
		// System.err.println("Location: " + location);
		//			
		// firePropertyChange(IPrismScreen.IMAGE_PATH, old, value);
		// } else
		screen.setPropertyValue(_propertyId, _value);

	}

	/**
	 * @return Returns the screen.
	 */
	public IPrismScreen getScreen() {
		return screen;
	}

	public Object getAdapter(Class _adapter) {
		return Platform.getAdapterManager().getAdapter(screen, _adapter);
	}

	public void childPropertyChange(final Object _child, final String _type,
			final Object _newValue) {
		if (_child instanceof PointerLocation) {
//			PointerLocation ptrLoc = (PointerLocation) _child;
//			int idx = screen.getPathLocationsList().indexOf(
//					ptrLoc.getJLocation());
//			java.awt.Point newPt = screen.getPathLocation(idx);
			java.awt.Point newPt = screen.getPointerStart();
			newPt.setLocation(((Point) _newValue).x, ((Point) _newValue).y);
		} else if (_child instanceof StickyNoteAdapter) {
			StickyNoteAdapter _note = (StickyNoteAdapter) _child;
			int idx = screen.getAnnotationsList().indexOf(_note.getAnnotation());
			IPrismAnnotation annotation = screen.getAnnotation(idx);

			if (IPrismAnnotation.LOCATION.equals(_type)) {
				// newValue instanceof Rectangle
				annotation.setLocation(new java.awt.Point(
						((Rectangle) _newValue).getLocation().x,
						((Rectangle) _newValue).getLocation().y));
				annotation.setHeight(((Rectangle) _newValue).height);
				annotation.setWidth(((Rectangle) _newValue).width);
			}
			if (IPrismAnnotation.TEXT.equals(_type)) {
				annotation.setText((String) _newValue);
			}
		}
		
//		System.err.println("--------Child changed-------");
		screenDumpChildren();
//		System.err.println("--------End child changed-------");
	}

	private void screenDumpChildren() {
		List annotations = screen.getAnnotationsList();
		List ptrLocs = screen.getPathLocationsList();
		Iterator it = annotations.iterator();

		int i = 0;
		while (it.hasNext()) {
			System.err.println(((IPrismAnnotation) it.next()).getText());
			i++;
		}

		System.err.println(i + " Annotations.");

		it = ptrLocs.iterator();

		i = 0;
		while (it.hasNext()) {
			System.err.println(((java.awt.Point) it.next()).getLocation()
					.toString());
			i++;
		}

		System.err.println(i + " Locations.");

	}

}